package cn.bugstack.domain.trade.service.settlement;

import cn.bugstack.domain.trade.adapter.port.ITradePort;
import cn.bugstack.domain.trade.adapter.repository.ITradeRepository;
import cn.bugstack.domain.trade.model.aggregate.GroupBuyTeamSettlementAggregate;
import cn.bugstack.domain.trade.model.entity.*;
import cn.bugstack.domain.trade.service.ITradeSettlementOrderService;
import cn.bugstack.domain.trade.service.settlement.factory.TradeSettlementFilterFactory;
import cn.bugstack.types.design.framework.link.model2.chain.BusinessLinkedList;
import cn.bugstack.types.enums.NotifyTaskHTTPEnumVO;
import cn.bugstack.types.exception.AppException;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author: 小新
 * @Date: 2025/8/10 9:58
 * @Description:
 * @Version: v1.0
 */
@Service
@Slf4j
public class TradeSettlementOrderService implements ITradeSettlementOrderService {

    @Resource
    private ITradeRepository tradeRepository;

    @Resource
    ITradePort tradePort;

    @Resource
    ThreadPoolExecutor threadPoolExecutor;

    @Resource
    private BusinessLinkedList<TradeSettlementRuleCommandEntity, TradeSettlementFilterFactory.DynamicContext, TradeSettlementRuleFilterBackEntity> tradeSettlementFilter;

    @Override
    public TradePaySettlementEntity settlementMarketPayOrder(TradePaySuccessEntity tradePaySuccessEntity) throws Exception {

        log.info("拼团交易-支付订单结算:{} outTradeNo:{}", tradePaySuccessEntity.getUserId(), tradePaySuccessEntity.getOutTradeNo());
        // 1. 结算规则过滤
        TradeSettlementRuleFilterBackEntity tradeSettlementRuleFilterBackEntity = tradeSettlementFilter.apply(
                TradeSettlementRuleCommandEntity.builder()
                        .source(tradePaySuccessEntity.getSource())
                        .channel(tradePaySuccessEntity.getChannel())
                        .userId(tradePaySuccessEntity.getUserId())
                        .outTradeNo(tradePaySuccessEntity.getOutTradeNo())
                        .outTradeTime(tradePaySuccessEntity.getOutTradeTime())
                        .build(),
                new TradeSettlementFilterFactory.DynamicContext());

        String teamId = tradeSettlementRuleFilterBackEntity.getTeamId();

        // 2. 查询组团信息
        GroupBuyTeamEntity groupBuyTeamEntity = GroupBuyTeamEntity.builder()
                .teamId(tradeSettlementRuleFilterBackEntity.getTeamId())
                .activityId(tradeSettlementRuleFilterBackEntity.getActivityId())
                .targetCount(tradeSettlementRuleFilterBackEntity.getTargetCount())
                .completeCount(tradeSettlementRuleFilterBackEntity.getCompleteCount())
                .lockCount(tradeSettlementRuleFilterBackEntity.getLockCount())
                .status(tradeSettlementRuleFilterBackEntity.getStatus())
                .validStartTime(tradeSettlementRuleFilterBackEntity.getValidStartTime())
                .validEndTime(tradeSettlementRuleFilterBackEntity.getValidEndTime())
                .notifyConfigVO(tradeSettlementRuleFilterBackEntity.getNotifyConfigVO())
                .build();

        // 3. 构建聚合对象
        GroupBuyTeamSettlementAggregate groupBuyTeamSettlementAggregate = GroupBuyTeamSettlementAggregate.builder()
                .userEntity(UserEntity.builder().userId(tradePaySuccessEntity.getUserId()).build())
                .groupBuyTeamEntity(groupBuyTeamEntity)
                .tradePaySuccessEntity(tradePaySuccessEntity)
                .build();

        // 4. 拼团交易结算
        NotifyTaskEntity notifyTaskEntity = tradeRepository.settlementMarketPayOrder(groupBuyTeamSettlementAggregate);

        // 5. 回调处理- 失败处理同时也会有定时任务进行补偿处理
        if(null!=notifyTaskEntity){
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    Map<String, Integer> notifyResultMap=null;
                    try {
                        // 及时回调
                        notifyResultMap = execSettlementNotifyJob(notifyTaskEntity);
                    } catch (Exception e) {
                        throw new AppException(e.getMessage());
                    }
                    log.info("回调通知完结 result:{}", JSON.toJSONString(notifyResultMap));
                }
            });
        }

        // 6. 返回结算信息 - 公司中开发这样的流程时候，会根据外部需要进行值的设置
        return TradePaySettlementEntity.builder()
                .source(tradePaySuccessEntity.getSource())
                .channel(tradePaySuccessEntity.getChannel())
                .userId(tradePaySuccessEntity.getUserId())
                .teamId(teamId)
                .activityId(groupBuyTeamEntity.getActivityId())
                .outTradeNo(tradePaySuccessEntity.getOutTradeNo())
                .build();

    }
    @Override
    public Map<String, Integer> execSettlementNotifyJob(NotifyTaskEntity notifyTaskEntity) {
        log.info("拼团交易-执行结算通知回调指定 teamId:{},notifyTaskEntity:{}", notifyTaskEntity.getTeamId(),notifyTaskEntity);
        return execSettlementNotifyJob(Collections.singletonList(notifyTaskEntity));
    }

    @Override
    public Map<String, Integer> execSettlementNotifyJob() throws Exception {
        log.info("拼团交易-执行结算通知回调");
        // 查询未执行任务
        List<NotifyTaskEntity> notifyTaskEntityList = tradeRepository.queryUnExecutedNotifyTaskList();
        return execSettlementNotifyJob(notifyTaskEntityList);
    }

    @Override
    public Map<String, Integer> execSettlementNotifyJob(String teamId) throws Exception {
        log.info("拼团交易-执行结算通知回调指定 teamId:{}", teamId);
        List<NotifyTaskEntity> notifyTaskEntityList = tradeRepository.queryUnExecutedNotifyTaskList(teamId);
        return execSettlementNotifyJob(notifyTaskEntityList);
    }

    private Map<String, Integer> execSettlementNotifyJob(List<NotifyTaskEntity> notifyTaskEntityList) {
        int successCount = 0;
        int errorCount = 0;
        int retryCount = 0;
        for (NotifyTaskEntity notifyTaskEntity : notifyTaskEntityList) {
            // 回调处理
            String response = tradePort.groupBuyNotify(notifyTaskEntity);

            // 更新回调任务状态
            if(NotifyTaskHTTPEnumVO.SUCCESS.getCode().equals(response)){
                int updateCount=tradeRepository.updateNotifyTaskStatusSuccess(notifyTaskEntity.getTeamId());
                if(1==updateCount){
                    successCount+=1;
                }
            }else if(NotifyTaskHTTPEnumVO.ERROR.getCode().equals(response)){
                if(notifyTaskEntity.getNotifyCount()<5){
                    int updateCount=tradeRepository.updateNotifyTaskStatusError(notifyTaskEntity.getTeamId());
                    if(1==updateCount){
                        errorCount+=1;
                    }
                }else {
                    int updateCount=tradeRepository.updateNotifyTaskStatusRetry(notifyTaskEntity.getTeamId());
                    if(1==updateCount){
                        retryCount+=1;
                    }
                }
            }
        }
        return getNotifyResultMap(notifyTaskEntityList, successCount, errorCount, retryCount);
    }

    private static Map<String, Integer> getNotifyResultMap(List<NotifyTaskEntity> notifyTaskEntityList, int successCount, int errorCount, int retryCount) {
        Map<String, Integer> resultMap = new HashMap<>();
        resultMap.put("waitCount", notifyTaskEntityList.size());
        resultMap.put("successCount", successCount);
        resultMap.put("errorCount", errorCount);
        resultMap.put("retryCount", retryCount);
        return resultMap;
    }
}
